package com.ruoyi.back.service.impl

import cn.hutool.core.bean.BeanUtil
import cn.hutool.core.date.DateUtil
import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper
import com.baomidou.mybatisplus.extension.plugins.pagination.Page
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
import com.baomidou.shaun.core.context.ProfileHolder
import com.baomidou.shaun.core.profile.TokenProfile
import com.ruoyi.app.common.Data
import com.ruoyi.back.domain.ClubJob
import com.ruoyi.back.domain.ClubJobData
import com.ruoyi.back.domain.vo.ClubJobDataVo
import com.ruoyi.back.mapper.ClubJobDataMapper
import com.ruoyi.back.service.ClubJobDataService
import com.ruoyi.back.service.ClubJobService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import java.util.*

@Service
class ClubJobDataServiceImpl : ServiceImpl<ClubJobDataMapper, ClubJobData>(), ClubJobDataService {

    @Autowired
    private lateinit var clubJobService: ClubJobService

    override fun todayCount(clubJobId: Long): Pair<Long?, Long?> = getByDay(Date(), clubJobId)

    override fun yesterdayCount(clubJobId: Long): Pair<Long?, Long?> =
        getByDay(DateUtil.offsetDay(Date(), -1), clubJobId)

    override fun weekCount(clubJobId: Long): Pair<Long?, Long?> {

        val beginDate = DateUtil.offsetDay(Date(), -7)
        val endDate = DateUtil.date()
        return (list(queryWeek(beginDate, endDate, clubJobId, 1)).takeIf { it.isNotEmpty() }
            ?.run { sumOf { it.count!! } } ?: 0) to (list(
            queryWeek(
                beginDate,
                endDate,
                clubJobId,
                2
            )
        ).takeIf { it.isNotEmpty() }
            ?.run { sumOf { it.count!! } } ?: 0)
    }

    override fun monthdayCount(clubJobId: Long): Pair<Long?, Long?> {
        return (list(queryMonth(clubJobId, 1)).takeIf { it.isNotEmpty() }
            ?.run { sumOf { it.count!! } } ?: 0) to (list(queryMonth(clubJobId, 2)).takeIf { it.isNotEmpty() }
            ?.run { sumOf { it.count!! } } ?: 0)
    }

    override fun totalCount(clubJobId: Long): Pair<Long?, Long?> {
        return (list(commonQuery(clubJobId, null)).takeIf { it.isNotEmpty() }
            ?.run { sumOf { it.count!! } } ?: 0) to (list(commonQuery(clubJobId, null)).takeIf { it.isNotEmpty() }
            ?.run { sumOf { it.count!! } } ?: 0)
    }

    override fun clubJobDataPage(clubJob: ClubJob): Page<ClubJobDataVo> =
        clubJobService.clubJobPage(clubJob).let {
            Page<ClubJobDataVo>().apply {
                BeanUtil.copyProperties(it, this)
                records = it.records?.takeIf { it.isNotEmpty() }?.run {
                    map {
                        tran(it)
                    }
                }
            }
        }

   override fun tran(clubJob: ClubJob): ClubJobDataVo =
        ClubJobDataVo().apply {
            BeanUtil.copyProperties(clubJob, this)
            todayCount = todayCount(clubJob.id!!).run { "${first ?: 0}/${second ?: 0}" }
            yesterdayCount = yesterdayCount(clubJob.id!!).run { "${first ?: 0}/${second ?: 0}" }
            weekCount = weekCount(clubJob.id!!).run { "${first ?: 0}/${second ?: 0}" }
            monthCount = monthdayCount(clubJob.id!!).run { "${first ?: 0}/${second ?: 0}" }
            totalCount = totalCount(clubJob.id!!).run { "${first ?: 0}/${second ?: 0}" }
        }

    override fun getTodayData(type: Int): ClubJobData? =
        DateUtil.date().run {
            getOne(KtQueryWrapper(ClubJobData::class.java)
                .eq(ClubJobData::type, type)
                .eq(ClubJobData::createBy, ProfileHolder.getProfile().id)
                .eq(ClubJobData::year, DateUtil.year(this))
                .eq(ClubJobData::month, DateUtil.month(this))
                .eq(ClubJobData::day, DateUtil.dayOfMonth(this))
                .last("limit 1"))
        }


    private val getByDay: (Date, Long) -> Pair<Long?, Long?> = { date, id ->

        getOne(queryDay(date, id, 1))?.count to getOne(queryDay(date, id, 2))?.count
    }


    val queryDay: (Date, Long, Int) -> KtQueryWrapper<ClubJobData> = { date, id, type ->
        commonQuery(id, type).apply {
            eq(ClubJobData::year, DateUtil.year(date))
            eq(ClubJobData::month, DateUtil.month(date))
            eq(ClubJobData::day, DateUtil.dayOfMonth(date))
        }
    }

    val commonQuery: (Long, Int?) -> KtQueryWrapper<ClubJobData> = { id, type ->
        KtQueryWrapper(ClubJobData::class.java)
            .eq(type != null, ClubJobData::type, type)
            .eq(ClubJobData::clubJobId, id)
            .last("limit 1")
    }

    val queryWeek: (Date, Date, Long, Int) -> KtQueryWrapper<ClubJobData> = { begin, end, id, type ->
        commonQuery(id, type).apply {
            if (DateUtil.month(begin) == DateUtil.month(end)) {
                eq(ClubJobData::month, DateUtil.month(begin))
            } else {
                `in`(ClubJobData::month, DateUtil.month(begin), DateUtil.month(end))
            }

            ge(ClubJobData::day, DateUtil.dayOfMonth(end))
            le(ClubJobData::day, DateUtil.dayOfMonth(begin))
        }
    }

    val queryMonth: (Long, Int) -> KtQueryWrapper<ClubJobData> = { id, type ->
        commonQuery(id, type).apply {
            eq(ClubJobData::month, DateUtil.month(DateUtil.date()))
        }
    }

}